package xpn.platform.common.config;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import xpn.platform.modules.security.ShiroAuthorizingRealm;
import xpn.platform.modules.security.ShiroSessionManager;

/**
 * Shiro 配置
 *
 * @author bobatkm Sep 7, 2017
 */
@Configuration
public class ShiroConfigurer {
	@Autowired
	XpnPlatformConfig xpnPlatformConfig;

	/**
	 * Apache Shiro 核心通过 Filter 来实现权限控制，ShiroFilterFactoryBean 负责加载过滤链。
	 * <p>
	 * Filter Chain定义说明 1、一个URL可以配置多个Filter，使用逗号分隔 ；2、当设置多个过滤器时，全部验证通过，才视为通过；
	 * 3、部分过滤器可指定参数，如perms，roles
	 */
	@Bean
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		// 1 设置securityManager
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);

		// 2 设置过滤链
		// 从配置文件中加载过滤链
		shiroFilterFactoryBean.setFilterChainDefinitionMap(xpnPlatformConfig.getSecurity().getFilterChainDefinitions());

		// 3 设置登录url
		shiroFilterFactoryBean.setLoginUrl("/security/login");

		// 4 设置无授权访问url
		shiroFilterFactoryBean.setUnauthorizedUrl("/security/unauthorized");

		return shiroFilterFactoryBean;
	}

	/*
	 * 设置登录和授权功能实现的Bean为ShiroAuthorizingRealm
	 */
	@Bean
	public ShiroAuthorizingRealm tokenRealm() {
		return new ShiroAuthorizingRealm();
	}

	@Bean("shiroSecurityManager")
	public SecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

		// 设置realm.
		securityManager.setRealm(tokenRealm());

		// 设置自定义的会话管理器
		securityManager.setSessionManager(sessionManager());
		return securityManager;
	}

	/**
	 * 启用Shiro权限检查注解
	 */
	@Bean
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
		proxyCreator.setProxyTargetClass(true);
		return proxyCreator;
	}

	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
		advisor.setSecurityManager(securityManager);
		return advisor;
	}

	/*
	 * 设置会话管理器为自定义的ShiroSessionManager，实现JWT功能
	 */
	@Bean
	public SessionManager sessionManager() {
		DefaultWebSessionManager sessionManager = new ShiroSessionManager();
		sessionManager.setGlobalSessionTimeout(1000 * 60 * 60 * 12);
		return sessionManager;
	}
}